package com.didi.gulimall.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.didi.gulimall.common.constant.OrderConstant;
import com.didi.gulimall.common.constant.OrderStatusEnum;
import com.didi.gulimall.common.entity.LocalMqEntity;
import com.didi.gulimall.common.to.MemberResponseVo;
import com.didi.gulimall.common.to.OrderBackVo;
import com.didi.gulimall.common.to.OrderSuccessVo;
import com.didi.gulimall.common.utils.PageUtils;
import com.didi.gulimall.common.utils.Query;
import com.didi.gulimall.common.utils.R;
import com.didi.gulimall.config.AlipayTemplate;
import com.didi.gulimall.mq.GuliRabbitTemplate;
import com.didi.gulimall.order.dao.OrderDao;
import com.didi.gulimall.order.entity.OrderEntity;
import com.didi.gulimall.order.entity.OrderItemEntity;
import com.didi.gulimall.order.entity.PaymentInfoEntity;
import com.didi.gulimall.order.interceptor.LoginUserInterceptor;
import com.didi.gulimall.order.service.OrderItemService;
import com.didi.gulimall.order.service.OrderService;
import com.didi.gulimall.order.service.PaymentInfoService;
import com.didi.gulimall.order.vo.PayAsyncVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;


@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {
    @Autowired
    private GuliRabbitTemplate guliRabbitTemplate;
    @Autowired
    private PaymentInfoService paymentInfoService;
    @Autowired
    private OrderItemService orderItemService;
    @Autowired
    private AlipayTemplate alipayTemplate;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),
                new QueryWrapper<OrderEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void orderBack(OrderBackVo orderBackVo) throws Exception {
        OrderEntity orderEntity = getIdByOrderSn(orderBackVo.getOrderSn());
        if (orderEntity == null || orderEntity.getStatus().equals(OrderStatusEnum.CANCLED.getCode()) || orderEntity.getStatus().equals(OrderStatusEnum.PAYED.getCode())) {
            return;
        }
        orderEntity.setStateDescription(OrderStatusEnum.TIMEOUT.getMsg());
        orderEntity.setStatus(OrderStatusEnum.CANCLED.getCode());
        //  向支付宝发收单消息
        alipayTemplate.cancel(orderEntity.getOrderSn());

        OrderBackVo release = new OrderBackVo();
        release.setOrderSn(orderEntity.getOrderSn());
        LocalMqEntity local = new LocalMqEntity();
        local.setBody(JSON.toJSONString(orderBackVo));
        local.setClassType("com.didi.gulimall.common.to.OrderBackVo");
        local.setExchange("order-event-exchange");
        local.setRouteKey("order.release.#");
        local.setId(UUID.randomUUID().toString());
        guliRabbitTemplate.sendConvertAndSend(local);
        baseMapper.updateById(orderEntity);
    }

    @Override
    public OrderEntity getIdByOrderSn(String orderSn) {
        return baseMapper.selectOne(new QueryWrapper<OrderEntity>().eq("order_sn", orderSn));
    }

    @Override
    public R memberOrderList() {
        MemberResponseVo memberResponseVo = LoginUserInterceptor.loginUser.get();
        Long id = memberResponseVo.getId();
        QueryWrapper<OrderEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("member_id", id)
                .eq("delete_status", OrderConstant.NOT_DELETED);
        List<OrderEntity> orderEntities = baseMapper.selectList(queryWrapper);
        List<OrderEntity> collect = orderEntities.stream().peek(orderEntity -> {
            String orderSn = orderEntity.getOrderSn();
            List<OrderItemEntity> orderItemEntities = orderItemService.list(new QueryWrapper<OrderItemEntity>().eq("order_sn", orderSn));
            orderEntity.setOrderItems(orderItemEntities);
        }).collect(Collectors.toList());
        return R.ok().put("data", collect);
    }

    @Override
    public void paymentSuccessful(PayAsyncVo payAsyncVo) {
        // 修改订单
        OrderEntity orderEntity = getIdByOrderSn(payAsyncVo.getOut_trade_no());
        if (orderEntity.getStatus().equals(OrderStatusEnum.PAYED.getCode())) {
            return;
        }
        orderEntity.setPayType(OrderConstant.PaymentType.ALIPAY.getCode());
        orderEntity.setSourceType(OrderConstant.PC_ORDER);
        orderEntity.setStatus(OrderStatusEnum.PAYED.getCode());
        orderEntity.setPaymentTime(new Date());
        baseMapper.updateById(orderEntity);
        // 想向支付表插入数据
        PaymentInfoEntity paymentInfoEntity = getPaymentInfoEntity(payAsyncVo, orderEntity.getId());
        paymentInfoService.save(paymentInfoEntity);

        // 扣减库存
        Integer integration = orderEntity.getIntegration();
        Integer growth = orderEntity.getGrowth();
        LocalMqEntity localMqEntity = new LocalMqEntity();
        OrderSuccessVo orderSuccessVo = new OrderSuccessVo();
        // 增加用户积分
        orderSuccessVo.setIntegration(integration);
        orderSuccessVo.setGrowth(growth);
        orderSuccessVo.setMemberId(orderEntity.getMemberId());
        orderSuccessVo.setOrderSn(orderEntity.getOrderSn());


        localMqEntity.setExchange("order-event-exchange");
        localMqEntity.setRouteKey("order.paysuccess.#");
        localMqEntity.setId(UUID.randomUUID().toString());
        localMqEntity.setClassType("com.didi.gulimall.common.to.OrderSuccessVo");
        localMqEntity.setBody(JSON.toJSONString(orderSuccessVo));
        guliRabbitTemplate.sendConvertAndSend(localMqEntity);

        // 购物车删除已经购买的商品
    }

    @Override
    public List<OrderEntity> getOrderVo(String totalOrderSn) {
        return baseMapper.getOrderVo(totalOrderSn);
    }


    private PaymentInfoEntity getPaymentInfoEntity(PayAsyncVo payAsyncVo, Long orderId) {
        PaymentInfoEntity paymentInfoEntity = new PaymentInfoEntity();
        paymentInfoEntity.setTradeNo(payAsyncVo.getTrade_no());
        paymentInfoEntity.setPaymentStatus(OrderStatusEnum.PAYED.getMsg());
        paymentInfoEntity.setCallbackContent(JSON.toJSONString(payAsyncVo));
        paymentInfoEntity.setOrderId(orderId);
        paymentInfoEntity.setTotalAmount(new BigDecimal(payAsyncVo.getReceipt_amount()));
        paymentInfoEntity.setSubject(payAsyncVo.getSubject());
        paymentInfoEntity.setCreateTime(new Date());
        paymentInfoEntity.setConfirmTime(new Date());
        paymentInfoEntity.setCallbackTime(new Date());
        return paymentInfoEntity;
    }

}